// Copyright 2010, Vanya Davidenko.
// Используемая кодировка: UTF-8.

#ifndef SCRW_MAP_REPLACER_H_
#define SCRW_MAP_REPLACER_H_

#include <vector>
#include <libv/check.h>
#include "set_recognizer.h"


namespace scrw
{

template<class TReplaceType>
class MapReplacer
{
  private:
    typedef SetRecognizer::StateID StateID;


  public:
    typedef SetRecognizer::Word Word;
    typedef ::std::map<Word, TReplaceType> WordMap;

    MapReplacer() {}


    MapReplacer(const WordMap& map,
                const bool case_sensitive,
                const TReplaceType& default_value = TReplaceType())
        : default_value_(default_value)
    {
        BuildSetRecognizer(map, case_sensitive);
        BuildStateMap(map);
    }


    const TReplaceType& Replace(const ::std::string& word) const
    {
        return Replace(word.data(), word.length());
    }


    // Возвращает пустую строку, если переданное слово не найдено.
    template<typename TAsciiChar>
    const TReplaceType& Replace(const TAsciiChar* word,
                                const ::std::ptrdiff_t word_size) const
    {
        const StateID s = set_recognizer_.Process(word, word_size);
        if ( !set_recognizer_.IsFinal(s) )
            return default_value_;
        return state_map_[s];
    }



  private:
    void BuildSetRecognizer(const WordMap& map, const bool case_sensitive)
    {
        SetRecognizer::WordsSet word_set;

        for ( typename WordMap::const_iterator \
              i = map.begin() ; i != map.end() ; ++i )
            word_set.insert(i->first);

        set_recognizer_ = SetRecognizer(word_set, case_sensitive);
        state_map_.reserve(set_recognizer_.num_state_ids());
        state_map_.resize(set_recognizer_.num_state_ids());
    }


    void BuildStateMap(const WordMap& map)
    {
        for ( typename WordMap::const_iterator \
              i = map.begin() ; i != map.end() ; ++i )
        {
            const StateID state_id =
                set_recognizer_.Process(i->first.data(), i->first.length());

            VERIFY(state_id < static_cast<StateID>(state_map_.size()));
            state_map_[state_id] = i->second;
        }
    }



    SetRecognizer set_recognizer_;
    ::std::vector<TReplaceType> state_map_;
    TReplaceType default_value_;
};

}

#endif  // SCRW_MAP_REPLACER_H_
